package com.coursehub.gateway.filter;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * JWT认证过滤器
 */
@Component
public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory<JwtAuthenticationFilter.Config> {
    
    private static final Logger log = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
    
    @Value("${jwt.secret:courseHubSecretKeyForJWTTokenGeneration2024}")
    private String jwtSecret;
    
    // 不需要认证的路径
    private static final List<String> EXCLUDED_PATHS = List.of(
            "/api/users/login",
            "/api/users/register",
            "/api/users/*/exists",
            "/api/courses/*/exists",
            "/api/chapters/*/exists",
            "/api/materials/*/exists",
            "/api/classes/*/exists",
            "/api/exercises/*/exists",
            "/api/exercises/validate/**",
            "/api/progress/validate/**",
            "/api/statistics/validate/**",
            "/actuator/**"
    );
    
    public JwtAuthenticationFilter() {
        super(Config.class);
    }
    
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            
            System.out.println("[DEBUG] API Gateway - JWT过滤器被调用，路径: " + path);
            
            // 检查是否为排除路径
            if (isExcludedPath(path)) {
                System.out.println("[DEBUG] API Gateway - 路径在排除列表中，跳过JWT验证: " + path);
                return chain.filter(exchange);
            }
            
            System.out.println("[DEBUG] API Gateway - 路径需要JWT验证: " + path);
            
            // 获取Authorization头
            String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
            
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                return handleUnauthorized(exchange);
            }
            
            String token = authHeader.substring(7);
            
            try {
                // 验证JWT token
                System.out.println("[DEBUG] API Gateway - 开始验证JWT token: " + token.substring(0, Math.min(20, token.length())) + "...");
                Claims claims = validateToken(token);
                
                String userId = claims.get("userId", String.class);
                String userAccount = claims.getSubject();
                String userName = claims.get("userName", String.class);
                
                System.out.println("[DEBUG] API Gateway - JWT验证成功，用户信息: userId=" + userId + ", userAccount=" + userAccount + ", userName=" + userName);
                log.debug("JWT验证成功，用户信息: userId={}, userAccount={}, userName={}", userId, userAccount, userName);
                
                // 将用户信息添加到请求头中，供下游服务使用
                System.out.println("[DEBUG] API Gateway - 添加用户头信息: X-User-Id=" + userId + ", X-User-Account=" + userAccount + ", X-User-Name=" + userName);
                ServerHttpRequest modifiedRequest = request.mutate()
                        .header("X-User-Id", userId)
                        .header("X-User-Account", userAccount)
                        .header("X-User-Name", userName)
                        .build();
                
                System.out.println("[DEBUG] API Gateway - 用户头信息已添加到请求中");
                log.debug("已添加用户头信息到请求中");
                
                ServerWebExchange modifiedExchange = exchange.mutate()
                        .request(modifiedRequest)
                        .build();
                
                return chain.filter(modifiedExchange);
                
            } catch (Exception e) {
                System.out.println("[DEBUG] API Gateway - JWT验证失败: " + e.getMessage());
                log.error("JWT验证失败: {}", e.getMessage());
                return handleUnauthorized(exchange);
            }
        };
    }
    
    private boolean isExcludedPath(String path) {
        return EXCLUDED_PATHS.stream().anyMatch(excludedPath -> {
            if (excludedPath.contains("*")) {
                // 处理通配符路径
                String pattern = excludedPath.replace("*", "[^/]*");
                return path.matches(pattern.replace("/", "\\/"));
            } else if (excludedPath.endsWith("/**")) {
                // 处理递归路径
                String prefix = excludedPath.substring(0, excludedPath.length() - 3);
                return path.startsWith(prefix);
            } else {
                // 精确匹配
                return path.equals(excludedPath);
            }
        });
    }
    
    private Claims validateToken(String token) {
        SecretKey key = Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8));
        
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
    
    private Mono<Void> handleUnauthorized(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }
    
    public static class Config {
        // 配置类，可以添加配置参数
    }
}